
#include "ConRaw.h"
#include "IO.h"

#define Pin_Validate(pin)			((pin)->port != 0)
#define Pin_GetState(pin)			IO_Get(pin)
#define Pin_SetState(pin, state)	IO_Set(pin, state)
#define Pin_SetLow(pin)				IO_Set(pin, 0)
#define Pin_SetHigh(pin)			IO_Set(pin, 1)

#define Pin_ConfigOut(pin)			IO_Config(pin, IO_Mode_OUT)
#define Pin_ConfigOD(pin)			IO_Config(pin, IO_Mode_OD)
#define Pin_ConfigInUp(pin)			IO_Config(pin, IO_Mode_IPU)
#define Pin_ConfigAFOD(pin)			IO_Config(pin, IO_Mode_AFOD)
#define Pin_ConfigAFPP(pin)			IO_Config(pin, IO_Mode_AFPP)
#define Pin_ConfigIn(pin)			IO_Config(pin, IO_Mode_IN)

typedef struct ConRawTag ConRaw;

struct ConRawTag{
	connector_t con;
	const IO_T vcc;
	const IO_T check;
	const IO_T reset;
	const IO_T io;
	const IO_T clock;
	const IO_T c4;
	const IO_T c8;
};


static const ConMethod conRawMethod;
static const IO_T selectPins[2] = {
								{0, 0},
								{0, 0}
							};

static const ConRaw conRaws[1] = {
	
	[0] = {
		.con = {
			.method = &conRawMethod,
		},
		.vcc = {(void*)GPIOB, GPIO_PIN_3},
		.check = {0, 0},
		.reset = {(void*)GPIOA, GPIO_PIN_10},
		.io = {(void*)GPIOA, GPIO_PIN_9},
		.clock = {(void*)GPIOA, GPIO_PIN_8},
		.c4 = {0, 0},
		.c8 = {0, 0},
	},
};

static uint8_t ConRaw_Check(connector_t* con, uint8_t num){
	const ConRaw* c = (const ConRaw*) con;
	if(c){
		if(Pin_Validate(&c->check)){
			return Pin_GetState(&c->check) != 0 ? 0 : 1;
		}
		return 1; //SIM 卡默认一直存在
	}
	return 0;
}

static uint8_t ConRaw_SetVCC(connector_t* con, uint8_t voltage){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->vcc)){
		//低电平使能电源
		Pin_SetState(&c->vcc, ! voltage);
	}
	return 0;
}

static void ConRaw_SetReset(connector_t* con, uint8_t state){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->reset)){
		Pin_SetState(&c->reset, state);
	}
}

static uint8_t ConRaw_ConfigClock(connector_t* con, uint8_t conf){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->clock)){
		switch(conf)
		{
			case CON_CLK_TRANSPARENT:
			{
				Pin_ConfigAFPP(&c->clock);
			}
			break;

			case CON_CLK_BIT_HIGH:
			{
				Pin_SetHigh(&c->clock);
				Pin_ConfigOut(&c->clock);
			}
			break;

			case CON_CLK_BIT_LOW:
			{
				Pin_SetLow(&c->clock);
				Pin_ConfigOut(&c->clock);
			}
			break;
			default:
				return 2;
		}
		return 0;
	}
	return 1;
}

static void ConRaw_SetClock(connector_t* con, uint8_t state){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->clock)){
		Pin_SetState(&c->clock, state);
	}
}

static uint8_t ConRaw_ConfigIO(connector_t* con, uint8_t conf){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->io)){
		switch(conf)
		{
			case CON_IO_TRANSPARENT:
			{
				Pin_ConfigAFOD(&c->io);
			}
			break;

			case CON_IO_BIT_OUT:
			{
				Pin_SetHigh(&c->io);
				Pin_ConfigOut(&c->io);
			}
			break;

			case CON_IO_BIT_IN:
			{
				Pin_SetLow(&c->io);
				Pin_ConfigIn(&c->io);
			}
			break;
			default:
				return 2;
		}
		return 0;
	}
	return 1;
}

static void ConRaw_SetIO(connector_t* con, uint8_t state){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->io)){
		Pin_SetState(&c->io, state);
	}
}

static uint8_t ConRaw_GetIO(connector_t* con){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->io)){
		return Pin_GetState(&c->io);
	}
	return 2;
}

static void ConRaw_SetC4(connector_t* con, uint8_t state){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->c4)){
		Pin_SetState(&c->c4, state);
	}
}

static void ConRaw_SetC8(connector_t* con, uint8_t state){
	const ConRaw* c = (const ConRaw*) con;
	if(c && Pin_Validate(&c->c8)){
		Pin_SetState(&c->c8, state);
	}
}

static void ConRaw_SwitchTo(connector_t* con, uint8_t num){
	switch(num){
	case 0:{
//			Pin_SetLow(&selectPins[0]);
//			Pin_SetLow(&selectPins[1]);
	}
	break;
	case 1:{
//			Pin_SetHigh(&selectPins[0]);
//			Pin_SetLow(&selectPins[1]);
	}
	break;
	}
}


static const ConMethod conRawMethod = {
	.checkPresent = ConRaw_Check,
	.setVCC = ConRaw_SetVCC,
	.setReset = ConRaw_SetReset,
	.configClock = ConRaw_ConfigClock,
	.setClock = ConRaw_SetClock,
	.configIO = ConRaw_ConfigIO,
	.setIO = ConRaw_SetIO,
	.getIO = ConRaw_GetIO,
	.setC4 = ConRaw_SetC4,
	.setC8 = ConRaw_SetC8,
	.switchTo = ConRaw_SwitchTo,
};


connector_t* ConRaw_Get(uint8_t num){
	if(num < 2){
	//由两个卡槽共用，无论num是什么，都返回相同的con。
		return (connector_t*)&conRaws[0];
	}
	return (connector_t*)0;
}

static void ConRaw_DoInit(const ConRaw* con){
	Pin_ConfigOut(&con->vcc);
//		Pin_ConfigInUp(&con->check);
#if 1
	Pin_ConfigOut(&con->reset);
	Pin_ConfigAFOD(&con->io);
	Pin_ConfigAFPP(&con->clock);
#else
	Pin_ConfigOut(&con->reset);
	Pin_ConfigOut(&con->io);
	Pin_ConfigOut(&con->clock);
#endif 
//		Pin_ConfigOD(&con->c4);	
//		Pin_ConfigOD(&con->c8);
	
	ConRaw_SetVCC((connector_t* )con, 0);
	ConRaw_SetReset((connector_t* )con, 0);
//		ConRaw_SetC4((connector_t* )con, 0);
//		ConRaw_SetC8((connector_t* )con, 0);
}

#if 0
static void ConSelect_Init(void){
	Pin_ConfigOut(&selectPins[0]);
	Pin_ConfigOut(&selectPins[1]);
	
	Pin_SetLow(&selectPins[0]);
	Pin_SetLow(&selectPins[1]);
}
#endif 

void ConRaw_Init(void){
	uint8_t i;
	
	rcu_periph_clock_enable(RCU_GPIOB);
	for(i = 0; i < sizeof(conRaws)/sizeof(conRaws[0]); i++){
		ConRaw_DoInit(&conRaws[i]);
	}
#if 0
	ConSelect_Init();
#endif 
}




